home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
151-175
/
scopedisk168
/
tinytools
/
clip
/
clip.asm
< prev
next >
Wrap
Assembly Source File
|
1995-03-19
|
8KB
|
337 lines
; Clip input lines on specified locations and write result to standard output.
INCLUDE "/include/init.i"
; OPT D+
; Local Equs
MaxLineSize EQU 512
; Variable storage
STRUCT ArgArray,(4+1)*4
LONG StdIn
LONG StdOut
LONG ByteFetch
LONG ReadBytesLeft
LONG Count1
LONG Count2
LONG Delta1
LONG Delta2
LONG ID1StrPtr
LONG ID2StrPtr
LONG ID1Exclusive
LONG ID2Exclusive
SIZE
; Regs
Delta EQUR D4
Count EQUR D5
LineBufPtr EQUR D6
LineBufLeft EQUR D7
LineEndPtr EQUR A2
IDStrPtr EQUR A3
ErrorStrPtr EQUR A4
; Startup
STACK 4000
INIT
; Let ARP interpret the commandline
MOVE.L ComLineBase(GP),A0
MOVE.L ComLineSize(GP),D0
LEA HelpMsg(PC),A1
LEA ArgArray(GP),A2
LEA Template(PC),A3
MOVE.L A1,(A2)
CALL GADS
MOVE.L (A2),ErrorStrPtr
TST.L D0
BEQ ErrorExit
BMI ErrorExit
; Interpret the count values
MOVE.L ArgArray+0*4(GP),A0
BSR GetSignedNum
BEQ ErrorExit
MOVE.L D0,Count1(GP)
MOVE.L D1,Delta1(GP)
MOVE.L ArgArray+2*4(GP),A0
BSR GetSignedNum
BEQ ErrorExit
MOVE.L D0,Count2(GP)
MOVE.L D1,Delta2(GP)
; Interpret the ID strings
LEA EmptyString(PC),A1
MOVE.L ArgArray+1*4(GP),D0
BNE.S ID1StringSpecified
MOVE.L A1,D0
ID1StringSpecified:
MOVE.L D0,A0
CMP.B #'x',(A0)
BNE.S NoID1Exclusion
ADDQ.L #1,A0
ADDQ.L #1,ID1Exclusive(GP)
NoID1Exclusion:
MOVE.L A0,ID1StrPtr(GP)
MOVE.L ArgArray+3*4(GP),D0
BNE.S ID2StringSpecified
MOVE.L A1,D0
ID2StringSpecified:
MOVE.L D0,A0
CMP.B #'x',(A0)
BNE.S NoID2Exclusion
ADDQ.L #1,A0
ADDQ.L #1,ID2Exclusive(GP)
NoID2Exclusion:
MOVE.L A0,ID2StrPtr(GP)
; Open the standard input & output
CALL Input
MOVE.L D0,StdIn(GP)
CALL Output
MOVE.L D0,StdOut(GP)
; Allocate the read-line buffer
LEA OutOfMem(PC),ErrorStrPtr
MOVE.L #MaxLineSize+4+MaxLineSize,D0 ; 2 part buf with 0 term space.
MOVEQ #0,D1
CALL ArpAllocMem
MOVE.L D0,LineBufPtr
BEQ ErrorExit
; ** This is an intelligent ReadLine routine.
; Reinitialize the line buffer. (First part of dual buffer space)
DoForEachLine:
LEA ReadError(PC),ErrorStrPtr
MOVE.L LineBufPtr,LineEndPtr
MOVE.L #MaxLineSize,LineBufLeft
; Extract lines from the readbuffer into the line buffer.
BRA.S ExtractEntry
CopyLineBytes:
MOVE.L ByteFetch(GP),A0
ADDQ.L #1,ByteFetch(GP)
SUBQ.L #1,ReadBytesLeft(GP)
MOVE.B (A0),D0
CMP.B #10,D0
BEQ.S GotLine
MOVE.B D0,(LineEndPtr)+
SUBQ.L #1,LineBufLeft
BEQ.S GotLine
ExtractEntry:
TST.L ReadBytesLeft(GP) ; Stack vars 0 init
BNE CopyLineBytes
; Refill the read buffer.
MOVE.L StdIn(GP),D1
MOVE.L LineBufPtr,D2
MOVE.L #MaxLineSize,D3
ADD.L D3,D2
ADDQ.L #4,D2
CALL Read
TST.L D0
BMI ErrorExit
BNE.S NotYetDone
CMP.L LineBufPtr,LineEndPtr
BEQ.S Exit
NotYetDone:
MOVE.L D2,ByteFetch(GP)
MOVE.L D0,ReadBytesLeft(GP)
BNE CopyLineBytes
; Adjust end of line pointer and weed out empty lines
GotLine:
SUBQ.L #1,LineEndPtr
CMP.L LineBufPtr,LineEndPtr
BLO DoForEachLine
; Find the initial clip postition
MOVE.L LineBufPtr,A0
MOVE.L Delta1(GP),Delta
BPL.S InitialPosSet
MOVE.L LineEndPtr,A0
InitialPosSet:
MOVE.L Count1(GP),Count
MOVE.L ID1StrPtr(GP),IDStrPtr
BSR.S FindClipPosition
BNE DoForEachLine
MOVE.L A0,D3
; Find the secondary clip postition.
MOVE.L Delta2(GP),Delta
MOVE.L Count2(GP),Count
MOVE.L ID2StrPtr(GP),IDStrPtr
BSR.S FindClipPosition
BNE DoForEachLine
; Adjust for direction, adjust for exclusion and compute the length.
MOVE.L ID1Exclusive(GP),D0
MOVE.L ID2Exclusive(GP),D1
CMP.L A0,D3
BHI.S InvertedDirection
EXG D0,D1
EXG A0,D3
InvertedDirection:
ADD.L D1,A0
SUB.L D0,D3
SUB.L A0,D3
BMI DoForEachLine
ADDQ.L #2,D3
; Terminate with a LF and write the line clip.
LEA WriteError(PC),ErrorStrPtr
MOVE.B #10,-1(A0,D3.L)
MOVE.L StdOut(GP),D1
MOVE.L A0,D2
CALL Write
CMP.L D0,D3
BNE.S ErrorExit
WriteDone:
; Check if user hit ^C
SkipWrite:
SUB.L A1,A1
CALL CheckAbort
MOVE.L A1,ErrorStrPtr
TST.L D0
BNE.S ErrorExit
BRA DoForEachLine
; Done, cleanup
Exit:
CLR.W ReturnCode(GP)
SUB.L ErrorStrPtr,ErrorStrPtr
ErrorExit:
; Display error string, if any, and exit
MOVE.L ErrorStrPtr,D0
BEQ.S NoErrorMsg
MOVE.L D0,A1
CALL Puts
NoErrorMsg:
RTS
; Subroutines
; This subroutine tried to find the CNTth position in the current line (relative
; to the initial position) which matches the ID string.
; I : A0 = Initial search position
; O : A0 = Clip position
; : Z=1 if search succeeded.
; : LineBufPtr,LineEndPtr,Delta,Count,IDStrPtr should be initialized
FindClipPosition:
; Set the boundary to check with in D0 (Given position movement direction)
MOVE.L LineBufPtr,D0
TST.L Delta
BMI.S FetchedRelevantBoundary
MOVE.L LineEndPtr,D0
FetchedRelevantBoundary:
; Check if all matches found or boundary reached. If not move current position.
TST.L Count
CheckNextByte:
BEQ.S GotClipPosition
NoByteMatch:
CMP.L D0,A0
BEQ.S AtLineBoundary
ADD.L Delta,A0
; Check byte on the current position matched the ID string.
TST.B (IDStrPtr)
BEQ.S ByteMatched
MOVE.L IDStrPtr,A1
MOVE.B (A0),D1
TryToMatchNextByte:
CMP.B (A1)+,D1
BEQ.S ByteMatched
TST.B (A1)
BEQ NoByteMatch
BRA TryToMatchNextByte
ByteMatched:
SUBQ.L #1,Count
BRA CheckNextByte
; Done. Take care of the Z-flag.
AtLineBoundary:
TST.B (IDStrPtr)
GotClipPosition:
RTS
; This sub decodes an ASCII buffer containing a signed number to a positive
; number and a sign boolean. It also sets ErrorStrPtr to "Invalid count"
; I : A0 = Ptr ASCII buffer
; O : D0.L = Integer >= 0
; : D1.L = +1 if positive, -1 if negative
; : Z = 1 if error
GetSignedNum:
LEA InvalidCnt(PC),ErrorStrPtr
MOVEQ #-1,D1
CMP.B #'-',(A0)+
BEQ.S ConvertToLong
MOVEQ #+1,D1
CMP.B #'+',-(A0)
BNE.S ConvertToLong
ADDQ.L #1,A0
ConvertToLong:
MOVE.L D1,-(SP)
CALL Atol
MOVEM.L (SP)+,D1
RTS
; The string section
Template:
DC.B 'CNT1/a,ID1/k,CNT2/a,ID2/k',0
HelpMsg:
DC.B 'Clip - Pipe through clipped lines.',10
DC.B 'Usage: Clip <Cnt1> [ID1 [x]"charlist"] <RelCnt2> [ID2 [x]"charlist"]',0
OutOfMem:
DC.B 'Out of memory!',0
InvalidCnt:
DC.B 'Invalid count',0
ReadError:
DC.B 'Error while reading',0
WriteError:
DC.B 'Error while writing',0
EmptyString:
DC.B 0
CNOP 0,2
END